package com.mojito.gorm.session;

import com.mojito.gorm.annotation.Select;
import com.mojito.gorm.bind.GormMapperRegistry;
import com.mojito.gorm.executor.GormExecutor;
import com.mojito.gorm.executor.impl.SimpleGormExecutor;
import com.mojito.gorm.map.OperateTypeEnum;
import com.mojito.gorm.map.SqlMapInfo;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @author mojito
 */
@Slf4j
public class GormConfiguration {
    /**
     * 全局配置文件
     */
    public static final ResourceBundle properties;

    static {
        properties = ResourceBundle.getBundle("gorm");
    }

    /**
     * 存放mapper对应的代理工厂
     */
    private final GormMapperRegistry MAPPER_REGISTRY = new GormMapperRegistry();

    /**
     * 存放所有的mapper的全路径
     */
    private final List<String> mappersPath = new ArrayList<>(32);

    public final Map<String, SqlMapInfo> sqlMaps = new HashMap<>(32);

    public GormExecutor newExecutor() {
        return new SimpleGormExecutor();
    }

    public <T> T getMapper(Class<T> clazz, GormSession session) {
        return MAPPER_REGISTRY.getMapper(clazz, session);
    }

    public void config() {
        String basePackage = properties.getString("mapper.path");
        scanPackage(basePackage);
    }

    private void scanPackage(String basePackage) {
        String classpath = GormSession.class.getResource("/").getPath();
        basePackage = basePackage.replace(".", File.separator);
        String scanRootPath = classpath + basePackage;
        scanPath(new File(scanRootPath));
        //加载所有扫描的类
        for (String className : mappersPath) {
            className = className.replace(classpath, "").replace("/", ".").replace(".class", "");
            Class<?> clazz = null;
            log.info("load class: {}", className);
            try {
                clazz = Class.forName(className);
                if (clazz.isInterface()) {
                    parseMapper(clazz);
                }
            } catch (ClassNotFoundException e) {
                log.error("class load error: {}", e);
            }
        }
    }

    /**
     * 解析注解,并注册代理工厂
     *
     * @param mapper
     */
    private void parseMapper(Class<?> mapper) {
        //注册代理工厂
        MAPPER_REGISTRY.addMapper(mapper);
        //解析注解
        Method[] methods = mapper.getMethods();
        for (Method method : methods) {
            if (method.isDefault()) {
                continue;
            }
            if (method.isAnnotationPresent(Select.class)) {
                String keyName = method.getDeclaringClass().getName() + "." + method.getName();
                Select select = method.getAnnotation(Select.class);
                sqlMaps.put(keyName, new SqlMapInfo(select.value(), select.type(), OperateTypeEnum.SELECT));
            }
        }
    }

    private void scanPath(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                scanPath(f);
            }
        } else {
            //文件添加到mapperpath中
            if (file.getName().endsWith(".class")) {
                mappersPath.add(file.getPath());
            }
        }
    }
}
